#include <stdio.h>
#include <stdlib.h>

#include "CodeTimeing.h"
#include "OldParser.h"
#include "Parser.h"
#include "RunTests.h"
#include "NewTests.h"
#include "RegExp.h"

#define LOOPS 25
#define TEST_FILE "OldParser.cpp"

const char *Names[] =
{
  "General",
  "1",
  "2",
  "3",
  "4",
  "5",
  "6",
  "7",
  "8",
  "9",
  "Mix",
  "No Match"
};

void PushTokens1(int tset);
void PushTokens2(int tset);
void KillNewLines(char *sp);
void Validate(int hash, int closef);
void Sizes(int hash, int closef);
void TimeTest(int hash, int closef);

void ValidateCS   (int sen, int hash, int closef);
void PushTokensS  (int sen, int hash, int closef);
void PushTokensSB1(int sen, int hash, int closef);
void PushTokensSB2(int sen, int hash, int closef);
void PushTokensSM1(int sen, int hash, int closef);
void PushTokensSM2(int sen, int hash, int closef);
void PushTokensSW1(int sen, int hash, int closef);
void PushTokensSW2(int sen, int hash, int closef);
void CaseBestTimeTest  (int hash, int closef);
void CaseMiddleTimeTest(int hash, int closef);
void CaseWorstTimeTest (int hash, int closef);
void CaseTest    (void);

void SwitchToTest(void);

void WildcardPerformance(int hash, int closef);

int main(void)
{
    /* Run some RegEx specific tests. */
  TestRegExp();

  //RunTests();
  //RunNewTests();
/*
  #ifdef SAFEALLOC_H
    DumpAllocatedMemMin();
    DumpAllocStatus();
  #endif
  return 0;
*/
  int i;

    /* Cycle through all the performance related optoins */
  for(i = 0; i <= ((1 << 0) | (1 << 1)); ++i)
  {
    int closef = !(i & (1 << 0));
    int hash   =   i & (1 << 1) ;
    printf("---------------- ");
    if(closef) printf("Close File  "); else printf("            ");
    if(hash)   printf("hash  ");       else printf("      ");
    printf("----------------\n");

      /* Compair the old parsers output, with the new parsers out put.        *
       *   Generally, the old parsers output is correct, so we can rely on    *
       *   this to perform some more extensive testing without haveing a      *
       *   calculate the correct output by hand.                              */
    Validate(hash, closef);
      /* Compute the memory usage deltas between the old and new version      */
    Sizes   (hash, closef);
      /* Run some general performance tests against the old version           */
    TimeTest(hash, closef);
      /* Test the wildcard performance, vs the old linear parsing method.     */
    WildcardPerformance(hash, closef);
  }

    /* Run some generalized tests against the Parsers with a "Good" data set  *
     *   a "Average" data set, and a "Bad" data set.                          */
  CaseTest();

    /* Test to make sure a switchto value of -2 works correctly. This is      *
     *   currently not automated.                                             */
  //SwitchToTest();

    /* Run all the tests defined by Data/Test.txt. All of these tests are     *
     *   to stress a variety of different aspects of the parser with larger   *
     *   data sets then the ones present in these .cpp files.                 */
  RunTests();

    /* Runs a variety of newer test that targets v 8.9. Namely, several of    *
     *   ParserEnable() options are cycled through.                           */
  RunNewTests();

  return 0;
}

void TimeTest(int hash, int closef)
{
  float ctime;
  float itime;
  int tset;
  int i;
  char *buffer;

  for(tset = 0; tset < (int)(sizeof(Names) / sizeof(char *)); ++tset)
  {
    printf("%-10s:", Names[tset]);
    SCodeTime();
    printf("  --  ");

    for(i = 0; i < LOOPS; ++i)
    {
      OldParser::ParserInit(TEST_FILE, 1024);

      PushTokens1(tset);

      for(buffer = OldParser::GrabToken(); buffer; buffer = OldParser::GrabToken())
        free(buffer);

      OldParser::LoadFile(TEST_FILE);

      for(buffer = OldParser::GrabToken(); buffer; buffer = OldParser::GrabToken())
        free(buffer);

      OldParser::LoadFile(TEST_FILE);

      for(buffer = OldParser::GrabToken(); buffer; buffer = OldParser::GrabToken())
        free(buffer);

      OldParser::ParserDeInit();
    }

    ctime = CodeTime();

    SCodeTime();

    for(i = 0; i < LOOPS; ++i)
    {
      ParserInit(TEST_FILE, 1024);

      PushTokens2(tset);

      if(hash) ParserEnable(PARSER_HASH);
      if(closef) ParserEnable(PARSER_CLOSE_FILE);

      for(buffer = GrabToken(); buffer; buffer = GrabToken())
        free(buffer);

      LoadFile(TEST_FILE);

      for(buffer = GrabToken(); buffer; buffer = GrabToken())
        free(buffer);

      LoadFile(TEST_FILE);

      for(buffer = GrabToken(); buffer; buffer = GrabToken())
        free(buffer);

      ParserDeInit();
    }

    itime = CodeTime();
    printf("  --  %5.1f%%\n", (1.0f - itime / ctime) * 100.0f);
  }

  printf("\n");
}

void Validate(int hash, int closef)
{
  int tset;

  for(tset = 0; tset < (int)(sizeof(Names) / sizeof(char *)); ++tset)
  {
    char *buffer[2];

    printf("Validate: %s\n", Names[tset]);

    OldParser::ParserInit(TEST_FILE, 1024);
    PushTokens1(tset);

    ParserInit(TEST_FILE, 1024);
    PushTokens2(tset);
    if(hash) ParserEnable(PARSER_HASH);
    if(closef) ParserEnable(PARSER_CLOSE_FILE);

    buffer[0] = OldParser::GrabToken();
    buffer[1] = GrabToken();

    while(buffer[0] && buffer[1])
    {
      if(!OldParser::Cmp(buffer[0], buffer[1]))
      {
        KillNewLines(buffer[0]); KillNewLines(buffer[1]);
        printf("Error: |%s| != |%s|\n", buffer[0], buffer[1]);
      }
      else
      {
        //KillNewLines(buffer[0]); KillNewLines(buffer[1]);
        //printf("       |%s| == |%s|\n", buffer[0], buffer[1]);
      }

      free(buffer[0]);
      free(buffer[1]);

      buffer[0] = OldParser::GrabToken();
      buffer[1] = GrabToken();
    }

    if(buffer[0] && !buffer[1])
      printf("Error: GrabTokenInt()\n");
    if(!buffer[0] && buffer[1])
      printf("Error: GrabToken()\n");

    OldParser::ParserDeInit();
    ParserDeInit();
  }

  printf("\n");
}

void Sizes(int hash, int closef)
{
  int tset;

  for(tset = 0; tset < (int)(sizeof(Names) / sizeof(char *)); ++tset)
  {
    char *buffer[2];

    printf("Memory Usage: %-10s: ", Names[tset]);

    OldParser::ParserInit(TEST_FILE, 1024);
    PushTokens1(tset);

    ParserInit(TEST_FILE, 1024);
    PushTokens2(tset);
    if(hash) ParserEnable(PARSER_HASH);
    if(closef) ParserEnable(PARSER_CLOSE_FILE);

    buffer[0] = OldParser::GrabToken();
    buffer[1] = GrabToken();

    free(buffer[0]);
    free(buffer[1]);

    printf("(%5d bytes) (%5d bytes)  --  %5.1f%% (%3d bytes)\n", OldParser::ParserMemoryUsage(), ParserMemoryUsage(), (float)ParserMemoryUsage() / OldParser::ParserMemoryUsage() * 100.0f - 100.0f, ParserMemoryUsage() - OldParser::ParserMemoryUsage());

    OldParser::ParserDeInit();
    ParserDeInit();
  }

  printf("\n");
}

void KillNewLines(char *sp)
{
  int read;
  int write;

  for(read = 0, write = -1; sp[read]; ++read)
    switch(sp[read])
    {
      case '\n':
      case '\r':
        sp[++write] = '|';
        break;
      default:
        sp[++write] = sp[read];
        break;
    }
  sp[++write] = 0;
}

void PushTokens1(int tset)
{
  OldParser::SetTokenSet(0);

  switch(tset)
  {
    case 0: // General
      OldParser::AddTokenSeparator("\"", 0,  1, 0, 0, 0);
      OldParser::AddTokenSeparator("/*", 0,  2, 0, 0, 0);
      OldParser::AddTokenSeparator(" " , 0, -1, 0, 0, 0);
      OldParser::AddTokenSeparator("\n", 0, -1, 0, 0, 0);
      OldParser::AddTokenSeparator("\r", 0, -1, 0, 0, 0);
      OldParser::AddTokenSeparator("\t", 0, -1, 0, 0, 0);

        /* Set up the token set that will handle the strings */
      OldParser::AddTokenSet();
      OldParser::AddTokenSeparator("\\\"", 0, -1, 1, 0, 0);
      OldParser::AddTokenSeparator("\"",   0,  0, 0, 0, 0);

        /* Set up the token set that will handle all comments */
      OldParser::AddTokenSet();
      OldParser::AddTokenSeparator("*/", 0, 0, 0, 0, 0);
      break;

    case 1:
      OldParser::AddTokenSeparator(" ",  0, -1, 0, 0, 0);
      OldParser::AddTokenSeparator("\n", 0, -1, 0, 0, 0);
      OldParser::AddTokenSeparator("\r", 0, -1, 0, 0, 0);
      OldParser::AddTokenSeparator("\t", 0, -1, 0, 0, 0);
      OldParser::AddTokenSeparator(";",  0, -1, 0, 0, 0);
      OldParser::AddTokenSeparator("{",  0, -1, 0, 0, 0);
      OldParser::AddTokenSeparator("}",  0, -1, 0, 0, 0);
      break;

    case 2:
      OldParser::AddTokenSeparator("\r\n", 0, -1, 0, 0, 0);
      OldParser::AddTokenSeparator("sp",   0, -1, 0, 0, 0);
      OldParser::AddTokenSeparator("to",   0, -1, 0, 0, 0);
      OldParser::AddTokenSeparator("ts",   0, -1, 0, 0, 0);
      OldParser::AddTokenSeparator("->",   0, -1, 0, 0, 0);
      OldParser::AddTokenSeparator("ch",   0, -1, 0, 0, 0);
      break;

    case 3:
      OldParser::AddTokenSeparator("cha", 0, -1, 0, 0, 0);
      OldParser::AddTokenSeparator("int", 0, -1, 0, 0, 0);
      OldParser::AddTokenSeparator("foo", 0, -1, 0, 0, 0);
      OldParser::AddTokenSeparator("bar", 0, -1, 0, 0, 0);
      OldParser::AddTokenSeparator("/* ", 0, -1, 0, 0, 0);
      OldParser::AddTokenSeparator(" */", 0, -1, 0, 0, 0);
      break;

    case 4:
      OldParser::AddTokenSeparator("int ",  0, -1, 0, 0, 0);
      OldParser::AddTokenSeparator("char",  0, -1, 0, 0, 0);
      OldParser::AddTokenSeparator("long",  0, -1, 0, 0, 0);
      OldParser::AddTokenSeparator(" /* ",  0, -1, 0, 0, 0);
      OldParser::AddTokenSeparator(" */\n", 0, -1, 0, 0, 0);
      break;

    case 5:
      OldParser::AddTokenSeparator("Token", 0, -1, 0, 0, 0);
      OldParser::AddTokenSeparator("Retur", 0, -1, 0, 0, 0);
      OldParser::AddTokenSeparator(" int ", 0, -1, 0, 0, 0);
      OldParser::AddTokenSeparator("char ", 0, -1, 0, 0, 0);
      OldParser::AddTokenSeparator("long ", 0, -1, 0, 0, 0);
      break;

    case 6:
      OldParser::AddTokenSeparator("Token ", 0, -1, 0, 0, 0);
      OldParser::AddTokenSeparator("Return", 0, -1, 0, 0, 0);
      OldParser::AddTokenSeparator("return", 0, -1, 0, 0, 0);
      break;

    case 7:
      OldParser::AddTokenSeparator("Return ", 0, -1, 0, 0, 0);
      OldParser::AddTokenSeparator("return ", 0, -1, 0, 0, 0);
      OldParser::AddTokenSeparator("Pointer", 0, -1, 0, 0, 0);
      OldParser::AddTokenSeparator("pointer", 0, -1, 0, 0, 0);
      break;

    case 8:
      OldParser::AddTokenSeparator("Pointer ", 0, -1, 0, 0, 0);
      OldParser::AddTokenSeparator("pointer ", 0, -1, 0, 0, 0);
      break;

    case 9:
      OldParser::AddTokenSeparator("Separator", 0, -1, 0, 0, 0);
      OldParser::AddTokenSeparator("separator", 0, -1, 0, 0, 0);
      OldParser::AddTokenSeparator("SwitchTo)", 0, -1, 0, 0, 0);
      break;

    case 10: // Mixed
      OldParser::AddTokenSeparator(" ", 0, -1, 0, 0, 0);
      OldParser::AddTokenSeparator("\n", 0, -1, 0, 0, 0);
      OldParser::AddTokenSeparator("\r", 0, -1, 0, 0, 0);
      OldParser::AddTokenSeparator("\t", 0, -1, 0, 0, 0);
      OldParser::AddTokenSeparator("return", 0, -1, 0, 0, 0);
      OldParser::AddTokenSeparator("Return", 0, -1, 0, 0, 0);
      OldParser::AddTokenSeparator("SwitchTo", 0, -1, 0, 0, 0);
      OldParser::AddTokenSeparator("Separator", 0, -1, 0, 0, 0);
      OldParser::AddTokenSeparator("separator", 0, -1, 0, 0, 0);
      break;

    case 11: // No Match
      OldParser::AddTokenSeparator("asdf;lkj", 0, -1, 0, 0, 0);
      OldParser::AddTokenSeparator("asdf;lkj", 0, -1, 0, 0, 0);
      OldParser::AddTokenSeparator("asdf;lkj", 0, -1, 0, 0, 0);
      OldParser::AddTokenSeparator("asdf;lkj", 0, -1, 0, 0, 0);
      OldParser::AddTokenSeparator("asdf;lkj", 0, -1, 0, 0, 0);
      OldParser::AddTokenSeparator("asdf;lkj", 0, -1, 0, 0, 0);
      OldParser::AddTokenSeparator("asdf;lkj", 0, -1, 0, 0, 0);
      OldParser::AddTokenSeparator("asdf;lkj", 0, -1, 0, 0, 0);
      OldParser::AddTokenSeparator("asdf;lkj", 0, -1, 0, 0, 0);
      break;
    }

  OldParser::SetTokenSet(0);
}

void PushTokens2(int tset)
{
  ParserEnable(PARSER_CONST_FILE_NAME | PARSER_CONST_LOAD_MEMORY |
                   PARSER_CONST_TOKEN_SEPS);

  SetTokenSet(0);

  switch(tset)
  {
    case 0: // General
      AddTokenSeparator("\"", 0,  1, 0, 0, 0);
      AddTokenSeparator("/*", 0,  2, 0, 0, 0);
      AddTokenSeparator(" " , 0, -1, 0, 0, 0);
      AddTokenSeparator("\n", 0, -1, 0, 0, 0);
      AddTokenSeparator("\r", 0, -1, 0, 0, 0);
      AddTokenSeparator("\t", 0, -1, 0, 0, 0);

        /* Set up the token set that will handle the strings */
      AddTokenSet();
      AddTokenSeparator("\\\"", 0, -1, 1, 0, 0);
      AddTokenSeparator("\"",   0,  0, 0, 0, 0);

        /* Set up the token set that will handle all comments */
      AddTokenSet();
      AddTokenSeparator("*/", 0, 0, 0, 0, 0);
      break;

    case 1:
      AddTokenSeparator(" ",  0, -1, 0, 0, 0);
      AddTokenSeparator("\n", 0, -1, 0, 0, 0);
      AddTokenSeparator("\r", 0, -1, 0, 0, 0);
      AddTokenSeparator("\t", 0, -1, 0, 0, 0);
      AddTokenSeparator(";",  0, -1, 0, 0, 0);
      AddTokenSeparator("{",  0, -1, 0, 0, 0);
      AddTokenSeparator("}",  0, -1, 0, 0, 0);
      break;

    case 2:
      AddTokenSeparator("\r\n", 0, -1, 0, 0, 0);
      AddTokenSeparator("sp",   0, -1, 0, 0, 0);
      AddTokenSeparator("to",   0, -1, 0, 0, 0);
      AddTokenSeparator("ts",   0, -1, 0, 0, 0);
      AddTokenSeparator("->",   0, -1, 0, 0, 0);
      AddTokenSeparator("ch",   0, -1, 0, 0, 0);
      break;

    case 3:
      AddTokenSeparator("cha", 0, -1, 0, 0, 0);
      AddTokenSeparator("int", 0, -1, 0, 0, 0);
      AddTokenSeparator("foo", 0, -1, 0, 0, 0);
      AddTokenSeparator("bar", 0, -1, 0, 0, 0);
      AddTokenSeparator("/* ", 0, -1, 0, 0, 0);
      AddTokenSeparator(" */", 0, -1, 0, 0, 0);
      break;

    case 4:
      AddTokenSeparator("int ",  0, -1, 0, 0, 0);
      AddTokenSeparator("char",  0, -1, 0, 0, 0);
      AddTokenSeparator("long",  0, -1, 0, 0, 0);
      AddTokenSeparator(" /* ",  0, -1, 0, 0, 0);
      AddTokenSeparator(" */\n", 0, -1, 0, 0, 0);
      break;

    case 5:
      AddTokenSeparator("Token", 0, -1, 0, 0, 0);
      AddTokenSeparator("Retur", 0, -1, 0, 0, 0);
      AddTokenSeparator(" int ", 0, -1, 0, 0, 0);
      AddTokenSeparator("char ", 0, -1, 0, 0, 0);
      AddTokenSeparator("long ", 0, -1, 0, 0, 0);
      break;

    case 6:
      AddTokenSeparator("Token ", 0, -1, 0, 0, 0);
      AddTokenSeparator("Return", 0, -1, 0, 0, 0);
      AddTokenSeparator("return", 0, -1, 0, 0, 0);
      break;

    case 7:
      AddTokenSeparator("Return ", 0, -1, 0, 0, 0);
      AddTokenSeparator("return ", 0, -1, 0, 0, 0);
      AddTokenSeparator("Pointer", 0, -1, 0, 0, 0);
      AddTokenSeparator("pointer", 0, -1, 0, 0, 0);
      break;

    case 8:
      AddTokenSeparator("Pointer ", 0, -1, 0, 0, 0);
      AddTokenSeparator("pointer ", 0, -1, 0, 0, 0);
      break;

    case 9:
      AddTokenSeparator("Separator", 0, -1, 0, 0, 0);
      AddTokenSeparator("separator", 0, -1, 0, 0, 0);
      AddTokenSeparator("SwitchTo)", 0, -1, 0, 0, 0);
      break;

    case 10: // Mixed
      AddTokenSeparator(" ", 0, -1, 0, 0, 0);
      AddTokenSeparator("\n", 0, -1, 0, 0, 0);
      AddTokenSeparator("\r", 0, -1, 0, 0, 0);
      AddTokenSeparator("\t", 0, -1, 0, 0, 0);
      AddTokenSeparator("return", 0, -1, 0, 0, 0);
      AddTokenSeparator("Return", 0, -1, 0, 0, 0);
      AddTokenSeparator("SwitchTo", 0, -1, 0, 0, 0);
      AddTokenSeparator("Separator", 0, -1, 0, 0, 0);
      AddTokenSeparator("separator", 0, -1, 0, 0, 0);
      break;

    case 11: // No Match
      AddTokenSeparator("asdf;lkj", 0, -1, 0, 0, 0);
      AddTokenSeparator("asdf;lkj", 0, -1, 0, 0, 0);
      AddTokenSeparator("asdf;lkj", 0, -1, 0, 0, 0);
      AddTokenSeparator("asdf;lkj", 0, -1, 0, 0, 0);
      AddTokenSeparator("asdf;lkj", 0, -1, 0, 0, 0);
      AddTokenSeparator("asdf;lkj", 0, -1, 0, 0, 0);
      AddTokenSeparator("asdf;lkj", 0, -1, 0, 0, 0);
      AddTokenSeparator("asdf;lkj", 0, -1, 0, 0, 0);
      AddTokenSeparator("asdf;lkj", 0, -1, 0, 0, 0);
      break;
    }

  SetTokenSet(0);
}









void CaseTest(void)
{
  int i;
  printf("------ Case Insensitive Tests\n");
  for(i = 0; i <= ((1 << 0) | (1 << 1) | (1 << 2)); ++i)
    ValidateCS(i & (1 << 1), i & (1 << 0), i & (1 << 2));

  printf("------ Best Case Scenario\n");
  for(i = 0; i <= ((1 << 0) | (1 << 1)); ++i)
    CaseBestTimeTest(i & (1 << 1), i & (1 << 0));

  printf("------ Average Case Scenario\n");
  for(i = 0; i <= ((1 << 0) | (1 << 1)); ++i)
    CaseMiddleTimeTest(i & (1 << 1), i & (1 << 0));

  printf("------ Worst Case Scenario\n");
  for(i = 0; i <= ((1 << 0) | (1 << 1)); ++i)
    CaseWorstTimeTest(i & (1 << 1), i & (1 << 0));

  printf("\n");
}








void CaseMiddleTimeTest(int hash, int closef)
{
  int sen;

  for(sen = 0; sen <= 1; ++sen)
  {
    float ctime;
    float itime;
    int i;
    char *buffer;

    if(closef)
      printf("Close: ");
    else
      printf("Open : ");

    if(!hash)
      if(!sen)
        printf("%-10s:", "Case Ins");
      else
        printf("%-10s:", "Case Sen");
    else
      if(!sen)
        printf("%-10s:", "Ins Hash");
      else
        printf("%-10s:", "Sen Hash");
    SCodeTime();
    printf("  --  ");

    for(i = 0; i < LOOPS; ++i)
    {
      PushTokensSM1(sen, hash, closef);

      for(buffer = OldParser::GrabToken(); buffer; buffer = OldParser::GrabToken())
        free(buffer);

      OldParser::LoadFile(TEST_FILE);

      for(buffer = OldParser::GrabToken(); buffer; buffer = OldParser::GrabToken())
        free(buffer);

      OldParser::LoadFile(TEST_FILE);

      for(buffer = OldParser::GrabToken(); buffer; buffer = OldParser::GrabToken())
        free(buffer);

      OldParser::ParserDeInit();
    }

    ctime = CodeTime();

    SCodeTime();

    for(i = 0; i < LOOPS; ++i)
    {
      PushTokensSM2(sen, hash, closef);

      for(buffer = GrabToken(); buffer; buffer = GrabToken())
        free(buffer);

      LoadFile(TEST_FILE);

      for(buffer = GrabToken(); buffer; buffer = GrabToken())
        free(buffer);

      LoadFile(TEST_FILE);

      for(buffer = GrabToken(); buffer; buffer = GrabToken())
        free(buffer);

      ParserDeInit();
    }

    itime = CodeTime();
    printf("  --  %5.1f%%\n", (1.0f - itime / ctime) * 100.0f);
  }
}

void PushTokensS(int sen, int hash, int closef)
{
  PushTokensSM1(sen, hash, closef);
  PushTokensSM2(sen, hash, closef);
}

void PushTokensSM1(int , int , int )
{
  OldParser::ParserInit(TEST_FILE, 1024);
  OldParser::AddTokenSeparator("sep", 0, -1, 0, 0, 0);
  OldParser::AddTokenSeparator("Sep", 0, -1, 0, 0, 0);
  OldParser::AddTokenSeparator("sEp", 0, -1, 0, 0, 0);
  OldParser::AddTokenSeparator("SEp", 0, -1, 0, 0, 0);
  OldParser::AddTokenSeparator("seP", 0, -1, 0, 0, 0);
  OldParser::AddTokenSeparator("SeP", 0, -1, 0, 0, 0);
  OldParser::AddTokenSeparator("sEP", 0, -1, 0, 0, 0);
  OldParser::AddTokenSeparator("SEP", 0, -1, 0, 0, 0);
  OldParser::AddTokenSeparator("A",   0, -1, 0, 0, 0);
  OldParser::AddTokenSeparator("a",   0, -1, 0, 0, 0);
  OldParser::AddTokenSeparator("B",   0, -1, 0, 0, 0);
  OldParser::AddTokenSeparator("b",   0, -1, 0, 0, 0);
  OldParser::AddTokenSeparator("C",   0, -1, 0, 0, 0);
  OldParser::AddTokenSeparator("c",   0, -1, 0, 0, 0);
  OldParser::AddTokenSeparator("D",   0, -1, 0, 0, 0);
  OldParser::AddTokenSeparator("d",   0, -1, 0, 0, 0);
  OldParser::AddTokenSeparator("E",   0, -1, 0, 0, 0);
  OldParser::AddTokenSeparator("e",   0, -1, 0, 0, 0);

  OldParser::AddTokenSeparator("-",   0, -1, 0, 0, 0);
  OldParser::AddTokenSeparator(" ",   0, -1, 0, 0, 0);
  OldParser::AddTokenSeparator("_",   0, -1, 0, 0, 0);
  OldParser::AddTokenSeparator("+",   0, -1, 0, 0, 0);
  OldParser::AddTokenSeparator("=",   0, -1, 0, 0, 0);
  OldParser::AddTokenSeparator("/",   0, -1, 0, 0, 0);
  OldParser::AddTokenSeparator("}",   0, -1, 0, 0, 0);
  OldParser::AddTokenSeparator("{",   0, -1, 0, 0, 0);
  OldParser::AddTokenSeparator(";",   0, -1, 0, 0, 0);
  OldParser::AddTokenSeparator(":",   0, -1, 0, 0, 0);
}

void PushTokensSM2(int sen, int hash, int closef)
{
  ParserInit(TEST_FILE, 1024);

  ParserEnable(PARSER_CONST_FILE_NAME | PARSER_CONST_LOAD_MEMORY |
                   PARSER_CONST_TOKEN_SEPS);

  if(!sen)ParserEnable(PARSER_CASE_INSENSITIVE);

  if(sen)AddTokenSeparator("sep", 0, -1, 0, 0, 0);
  if(sen)AddTokenSeparator("Sep", 0, -1, 0, 0, 0);
  if(sen)AddTokenSeparator("sEp", 0, -1, 0, 0, 0);
  if(sen)AddTokenSeparator("SEp", 0, -1, 0, 0, 0);
  if(sen)AddTokenSeparator("seP", 0, -1, 0, 0, 0);
  if(sen)AddTokenSeparator("SeP", 0, -1, 0, 0, 0);
  if(sen)AddTokenSeparator("sEP", 0, -1, 0, 0, 0);
         AddTokenSeparator("SEP", 0, -1, 0, 0, 0);
         AddTokenSeparator("A",   0, -1, 0, 0, 0);
  if(sen)AddTokenSeparator("a",   0, -1, 0, 0, 0);
         AddTokenSeparator("B",   0, -1, 0, 0, 0);
  if(sen)AddTokenSeparator("b",   0, -1, 0, 0, 0);
         AddTokenSeparator("C",   0, -1, 0, 0, 0);
  if(sen)AddTokenSeparator("c",   0, -1, 0, 0, 0);
         AddTokenSeparator("D",   0, -1, 0, 0, 0);
  if(sen)AddTokenSeparator("d",   0, -1, 0, 0, 0);
         AddTokenSeparator("E",   0, -1, 0, 0, 0);
  if(sen)AddTokenSeparator("e",   0, -1, 0, 0, 0);

         AddTokenSeparator("-",   0, -1, 0, 0, 0);
         AddTokenSeparator(" ",   0, -1, 0, 0, 0);
         AddTokenSeparator("_",   0, -1, 0, 0, 0);
         AddTokenSeparator("+",   0, -1, 0, 0, 0);
         AddTokenSeparator("=",   0, -1, 0, 0, 0);
         AddTokenSeparator("/",   0, -1, 0, 0, 0);
         AddTokenSeparator("}",   0, -1, 0, 0, 0);
         AddTokenSeparator("{",   0, -1, 0, 0, 0);
         AddTokenSeparator(";",   0, -1, 0, 0, 0);
         AddTokenSeparator(":",   0, -1, 0, 0, 0);

  if(hash) ParserEnable(PARSER_HASH);
  if(closef) ParserEnable(PARSER_CLOSE_FILE);
}

void PushTokensSB1(int , int , int )
{
  OldParser::ParserInit(TEST_FILE, 1024);
  OldParser::AddTokenSeparator("sep", 0, -1, 0, 0, 0);
  OldParser::AddTokenSeparator("Sep", 0, -1, 0, 0, 0);
  OldParser::AddTokenSeparator("sEp", 0, -1, 0, 0, 0);
  OldParser::AddTokenSeparator("SEp", 0, -1, 0, 0, 0);
  OldParser::AddTokenSeparator("seP", 0, -1, 0, 0, 0);
  OldParser::AddTokenSeparator("SeP", 0, -1, 0, 0, 0);
  OldParser::AddTokenSeparator("sEP", 0, -1, 0, 0, 0);
  OldParser::AddTokenSeparator("SEP", 0, -1, 0, 0, 0);
  OldParser::AddTokenSeparator("A",   0, -1, 0, 0, 0);
  OldParser::AddTokenSeparator("a",   0, -1, 0, 0, 0);
  OldParser::AddTokenSeparator("B",   0, -1, 0, 0, 0);
  OldParser::AddTokenSeparator("b",   0, -1, 0, 0, 0);
  OldParser::AddTokenSeparator("C",   0, -1, 0, 0, 0);
  OldParser::AddTokenSeparator("c",   0, -1, 0, 0, 0);
  OldParser::AddTokenSeparator("D",   0, -1, 0, 0, 0);
  OldParser::AddTokenSeparator("d",   0, -1, 0, 0, 0);
  OldParser::AddTokenSeparator("E",   0, -1, 0, 0, 0);
  OldParser::AddTokenSeparator("e",   0, -1, 0, 0, 0);
}

void PushTokensSB2(int sen, int hash, int closef)
{
  ParserInit(TEST_FILE, 1024);

  ParserEnable(PARSER_CONST_FILE_NAME | PARSER_CONST_LOAD_MEMORY |
                   PARSER_CONST_TOKEN_SEPS);

  if(!sen)ParserEnable(PARSER_CASE_INSENSITIVE);

  if(sen)AddTokenSeparator("sep", 0, -1, 0, 0, 0);
  if(sen)AddTokenSeparator("Sep", 0, -1, 0, 0, 0);
  if(sen)AddTokenSeparator("sEp", 0, -1, 0, 0, 0);
  if(sen)AddTokenSeparator("SEp", 0, -1, 0, 0, 0);
  if(sen)AddTokenSeparator("seP", 0, -1, 0, 0, 0);
  if(sen)AddTokenSeparator("SeP", 0, -1, 0, 0, 0);
  if(sen)AddTokenSeparator("sEP", 0, -1, 0, 0, 0);
         AddTokenSeparator("SEP", 0, -1, 0, 0, 0);
         AddTokenSeparator("A",   0, -1, 0, 0, 0);
  if(sen)AddTokenSeparator("a",   0, -1, 0, 0, 0);
         AddTokenSeparator("B",   0, -1, 0, 0, 0);
  if(sen)AddTokenSeparator("b",   0, -1, 0, 0, 0);
         AddTokenSeparator("C",   0, -1, 0, 0, 0);
  if(sen)AddTokenSeparator("c",   0, -1, 0, 0, 0);
         AddTokenSeparator("D",   0, -1, 0, 0, 0);
  if(sen)AddTokenSeparator("d",   0, -1, 0, 0, 0);
         AddTokenSeparator("E",   0, -1, 0, 0, 0);
  if(sen)AddTokenSeparator("e",   0, -1, 0, 0, 0);

  if(hash) ParserEnable(PARSER_HASH);
  if(closef) ParserEnable(PARSER_CLOSE_FILE);
}


void PushTokensSW1(int , int , int )
{
  OldParser::ParserInit(TEST_FILE, 1024);
  OldParser::AddTokenSeparator("-",   0, -1, 0, 0, 0);
  OldParser::AddTokenSeparator(" ",   0, -1, 0, 0, 0);
  OldParser::AddTokenSeparator("_",   0, -1, 0, 0, 0);
  OldParser::AddTokenSeparator("+",   0, -1, 0, 0, 0);
  OldParser::AddTokenSeparator("=",   0, -1, 0, 0, 0);
  OldParser::AddTokenSeparator("/",   0, -1, 0, 0, 0);
  OldParser::AddTokenSeparator("}",   0, -1, 0, 0, 0);
  OldParser::AddTokenSeparator("{",   0, -1, 0, 0, 0);
  OldParser::AddTokenSeparator(";",   0, -1, 0, 0, 0);
  OldParser::AddTokenSeparator(":",   0, -1, 0, 0, 0);

  OldParser::AddTokenSeparator("!",   0, -1, 0, 0, 0);
  OldParser::AddTokenSeparator("@",   0, -1, 0, 0, 0);
  OldParser::AddTokenSeparator("#",   0, -1, 0, 0, 0);
  OldParser::AddTokenSeparator("$",   0, -1, 0, 0, 0);
  OldParser::AddTokenSeparator("%",   0, -1, 0, 0, 0);
  OldParser::AddTokenSeparator("^",   0, -1, 0, 0, 0);
  OldParser::AddTokenSeparator("&",   0, -1, 0, 0, 0);
  OldParser::AddTokenSeparator("*",   0, -1, 0, 0, 0);
  OldParser::AddTokenSeparator("(",   0, -1, 0, 0, 0);
  OldParser::AddTokenSeparator(")",   0, -1, 0, 0, 0);
}

void PushTokensSW2(int sen, int hash, int closef)
{
  ParserInit(TEST_FILE, 1024);

  ParserEnable(PARSER_CONST_FILE_NAME | PARSER_CONST_LOAD_MEMORY |
                   PARSER_CONST_TOKEN_SEPS);

  if(!sen)ParserEnable(PARSER_CASE_INSENSITIVE);

  AddTokenSeparator("-",   0, -1, 0, 0, 0);
  AddTokenSeparator(" ",   0, -1, 0, 0, 0);
  AddTokenSeparator("_",   0, -1, 0, 0, 0);
  AddTokenSeparator("+",   0, -1, 0, 0, 0);
  AddTokenSeparator("=",   0, -1, 0, 0, 0);
  AddTokenSeparator("/",   0, -1, 0, 0, 0);
  AddTokenSeparator("}",   0, -1, 0, 0, 0);
  AddTokenSeparator("{",   0, -1, 0, 0, 0);
  AddTokenSeparator(";",   0, -1, 0, 0, 0);
  AddTokenSeparator(":",   0, -1, 0, 0, 0);

  AddTokenSeparator("!",   0, -1, 0, 0, 0);
  AddTokenSeparator("@",   0, -1, 0, 0, 0);
  AddTokenSeparator("#",   0, -1, 0, 0, 0);
  AddTokenSeparator("$",   0, -1, 0, 0, 0);
  AddTokenSeparator("%",   0, -1, 0, 0, 0);
  AddTokenSeparator("^",   0, -1, 0, 0, 0);
  AddTokenSeparator("&",   0, -1, 0, 0, 0);
  AddTokenSeparator("*",   0, -1, 0, 0, 0);
  AddTokenSeparator("(",   0, -1, 0, 0, 0);
  AddTokenSeparator(")",   0, -1, 0, 0, 0);

  if(hash) ParserEnable(PARSER_HASH);
  if(closef) ParserEnable(PARSER_CLOSE_FILE);
}


void ValidateCS(int sen, int hash, int closef)
{
  char *buffer[2];

  if(sen)
    printf("Validate: %s ", "Case Senstive  ");
  else
    printf("Validate: %s ", "Case Insenstive");
  if(hash) printf("(Hash)  "); else printf("        ");
  if(closef) printf("(Close File)  "); else printf("              ");
  printf("\n");

  PushTokensS(sen, hash, closef);

  buffer[0] = OldParser::GrabToken();
  buffer[1] = GrabToken();

  while(buffer[0] && buffer[1])
  {
    if(!OldParser::Cmp(buffer[0], buffer[1]))
    {
      KillNewLines(buffer[0]); KillNewLines(buffer[1]);
      printf("Error: |%s| != |%s|\n", buffer[0], buffer[1]);
    }
    else
    {
      //KillNewLines(buffer[0]); KillNewLines(buffer[1]);
      //printf("       |%s| == |%s|\n", buffer[0], buffer[1]);
    }

    free(buffer[0]);
    free(buffer[1]);

    buffer[0] = OldParser::GrabToken();
    buffer[1] = GrabToken();
  }

  if(buffer[0] && !buffer[1])
    printf("Error: GrabTokenInt()\n");
  if(!buffer[0] && buffer[1])
    printf("Error: GrabToken()\n");

  OldParser::ParserDeInit();
  ParserDeInit();
}

void CaseBestTimeTest(int hash, int closef)
{
  int sen;

  for(sen = 0; sen <= 1; ++sen)
  {
    float ctime;
    float itime;
    int i;
    char *buffer;

    if(closef)
      printf("Close: ");
    else
      printf("Open : ");

    if(!hash)
      if(!sen)
        printf("%-10s:", "Case Ins");
      else
        printf("%-10s:", "Case Sen");
    else
      if(!sen)
        printf("%-10s:", "Ins Hash");
      else
        printf("%-10s:", "Sen Hash");
    SCodeTime();
    printf("  --  ");

    for(i = 0; i < LOOPS; ++i)
    {
      PushTokensSB1(sen, hash, closef);

      for(buffer = OldParser::GrabToken(); buffer; buffer = OldParser::GrabToken())
        free(buffer);

      OldParser::LoadFile(TEST_FILE);

      for(buffer = OldParser::GrabToken(); buffer; buffer = OldParser::GrabToken())
        free(buffer);

      OldParser::LoadFile(TEST_FILE);

      for(buffer = OldParser::GrabToken(); buffer; buffer = OldParser::GrabToken())
        free(buffer);

      OldParser::ParserDeInit();
    }

    ctime = CodeTime();

    SCodeTime();

    for(i = 0; i < LOOPS; ++i)
    {
      PushTokensSB2(sen, hash, closef);

      for(buffer = GrabToken(); buffer; buffer = GrabToken())
        free(buffer);

      LoadFile(TEST_FILE);

      for(buffer = GrabToken(); buffer; buffer = GrabToken())
        free(buffer);

      LoadFile(TEST_FILE);

      for(buffer = GrabToken(); buffer; buffer = GrabToken())
        free(buffer);

      ParserDeInit();
    }

    itime = CodeTime();
    printf("  --  %5.1f%%\n", (1.0f - itime / ctime) * 100.0f);
  }
}

void CaseWorstTimeTest(int hash, int closef)
{
  int sen;

  for(sen = 0; sen <= 1; ++sen)
  {
    float ctime;
    float itime;
    int i;
    char *buffer;

    if(closef)
      printf("Close: ");
    else
      printf("Open : ");

    if(!hash)
      if(!sen)
        printf("%-10s:", "Case Ins");
      else
        printf("%-10s:", "Case Sen");
    else
      if(!sen)
        printf("%-10s:", "Ins Hash");
      else
        printf("%-10s:", "Sen Hash");
    SCodeTime();
    printf("  --  ");

    for(i = 0; i < LOOPS; ++i)
    {
      PushTokensSW1(sen, hash, closef);

      for(buffer = OldParser::GrabToken(); buffer; buffer = OldParser::GrabToken())
        free(buffer);

      OldParser::LoadFile(TEST_FILE);

      for(buffer = OldParser::GrabToken(); buffer; buffer = OldParser::GrabToken())
        free(buffer);

      OldParser::LoadFile(TEST_FILE);

      for(buffer = OldParser::GrabToken(); buffer; buffer = OldParser::GrabToken())
        free(buffer);

      OldParser::ParserDeInit();
    }

    ctime = CodeTime();

    SCodeTime();

    for(i = 0; i < LOOPS; ++i)
    {
      PushTokensSW2(sen, hash, closef);

      for(buffer = GrabToken(); buffer; buffer = GrabToken())
        free(buffer);

      LoadFile(TEST_FILE);

      for(buffer = GrabToken(); buffer; buffer = GrabToken())
        free(buffer);

      LoadFile(TEST_FILE);

      for(buffer = GrabToken(); buffer; buffer = GrabToken())
        free(buffer);

      ParserDeInit();
    }

    itime = CodeTime();
    printf("  --  %5.1f%%\n", (1.0f - itime / ctime) * 100.0f);
  }
}




#define TEST_STRING "s d f   e f\nasdfa\n\"foo bar\" d  e  f a     d   \"b b \" k n s a  c  s   e  f"

void SwitchToTest(void)
{
  char *buffer;

  ParserInit(0, 1024);
    // TSet 0
  AddTokenSeparator(" ",  0, -1, 0, 0, 0);
  AddTokenSeparator("\t", 0, -1, 0, 0, 0);
  AddTokenSeparator("\n", 0, -1, 0, 0, 0);
  AddTokenSeparator("\r", 0, -1, 0, 0, 0);
  AddTokenSeparator("a",  1,  1, 0, 0, 0);

  AddTokenSeparator("\"", 0,  2, 0, 0, 0);

    // TSet 1
  AddTokenSet();
  AddTokenSeparator("a",  1, -2, 0, 0, 0);
  AddTokenSeparator("\"", 0,  2, 0, 0, 0);

    // TSet 2
  AddTokenSet();
  AddTokenSeparator("\"", 0, -2, 0, 0, 0);

  SetTokenSet(0);

  LoadMemory(TEST_STRING);

  for(buffer = GrabToken(); buffer; buffer = GrabToken())
  {
    printf("%d: |%s|\n", GetTokenSet(), buffer);
    free(buffer);
  }

  ParserDeInit();
}

void WildcardPerformance(int hash, int closef)
{
  float ctime;
  float itime = 0.0f;
  int tset;
  int i;
  char *buffer;

  printf("%-10s:\n", "Wildcards");
  printf("%11s: ", "Validate");


  {
    int read;
    char *buffer[2];


    OldParser::ParserInit(TEST_FILE, 1024);
    OldParser::AddTokenSeparator("\n", 0, -1, 0, 0, 0);
    OldParser::AddTokenSeparator("\r", 0, -1, 0, 0, 0);
    OldParser::AddTokenSeparator(";",  0, -1, 0, 0, 0);

    ParserInit(TEST_FILE, 1024);

    ParserEnable(PARSER_WILDCARD);
    AddTokenSeparator("\n", 0, -1, 0, 0, 0);
    AddTokenSeparator("\r", 0, -1, 0, 0, 0);
    AddTokenSeparator("*;", 1, -1, 0, 0, 0);

    if(hash) ParserEnable(PARSER_HASH);
    if(closef) ParserEnable(PARSER_CLOSE_FILE);

    buffer[0] = OldParser::GrabToken();
    buffer[1] = GrabToken();

    while(buffer[0] && buffer[1])
    {
      for(read = 0; buffer[1][read]; ++read)
        if(buffer[1][read] == ';')
          buffer[1][read] = 0;
      if(!OldParser::Cmp(buffer[0], buffer[1]))
      {
        KillNewLines(buffer[0]); KillNewLines(buffer[1]);
        printf("Error: |%s| != |%s|\n", buffer[0], buffer[1]);
      }
      else
      {
        //KillNewLines(buffer[0]); KillNewLines(buffer[1]);
        //printf("       |%s| == |%s|\n", buffer[0], buffer[1]);
      }

      free(buffer[0]);
      free(buffer[1]);

      buffer[0] = OldParser::GrabToken();
      buffer[1] = GrabToken();
    }

    if(buffer[0] && !buffer[1])
      printf("Error: GrabTokenInt()\n");
    if(!buffer[0] && buffer[1])
      printf("Error: GrabToken()\n");

    OldParser::ParserDeInit();
    ParserDeInit();
    printf("\n");
  }




  printf("%11s: ", "Reg");
  SCodeTime();

  for(i = 0; i < LOOPS; ++i)
  {
    OldParser::ParserInit(TEST_FILE, 1024);

    OldParser::AddTokenSeparator("\n", 0, -1, 0, 0, 0);
    OldParser::AddTokenSeparator("\r", 0, -1, 0, 0, 0);
    OldParser::AddTokenSeparator(";",  1, -1, 0, 0, 0);

    for(buffer = OldParser::GrabToken(); buffer; buffer = OldParser::GrabToken())
      free(buffer);

    OldParser::LoadFile(TEST_FILE);

    for(buffer = OldParser::GrabToken(); buffer; buffer = OldParser::GrabToken())
      free(buffer);

    OldParser::LoadFile(TEST_FILE);

    for(buffer = OldParser::GrabToken(); buffer; buffer = OldParser::GrabToken())
      free(buffer);

    OldParser::ParserDeInit();
  }

  ctime = CodeTime();
  printf("\n");


  for(tset = 0; tset < 2; ++tset)
  {
    switch(tset)
    {
      case 0: printf("%11s: ", "Reg");  break;
      case 1: printf("%11s: ", "Wild"); break;
    }
    SCodeTime();

    for(i = 0; i < LOOPS; ++i)
    {
      ParserInit(TEST_FILE, 1024);

      if(tset) ParserEnable(PARSER_WILDCARD);

      AddTokenSeparator("\n", 0, -1, 0, 0, 0);
      AddTokenSeparator("\r", 0, -1, 0, 0, 0);
      if(!tset) AddTokenSeparator(";",  1, -1, 0, 0, 0);
      if( tset) AddTokenSeparator("*;", 1, -1, 0, 0, 0);

      if(hash) ParserEnable(PARSER_HASH);
      if(closef) ParserEnable(PARSER_CLOSE_FILE);

      for(buffer = GrabToken(); buffer; buffer = GrabToken())
        free(buffer);

      LoadFile(TEST_FILE);

      for(buffer = GrabToken(); buffer; buffer = GrabToken())
        free(buffer);

      LoadFile(TEST_FILE);

      for(buffer = GrabToken(); buffer; buffer = GrabToken())
        free(buffer);

      ParserDeInit();
    }

    itime = CodeTime();
    printf("\n");
  }

  printf("%11s: %5.1f%%\n", "8.0 vs Wild", (1.0f - itime / ctime) * 100.0f);

  printf("\n");
}
